/*****************************************************************************
 *   Copyright (C) 2008 John Schember <john@nachtimwald.com>                 *
 *                                                                           *
 *   This file is part of niwbillmanager.                                    *
 *                                                                           *
 *   niwbillmanager is free software: you can redistribute it and/or         *
 *   modify it under the terms of the GNU General Public License as          *
 *   published by the Free Software Foundation, either version 3 of the      *
 *   License, or (at your option) any later version.                         *
 *                                                                           *
 *   niwbillmanager is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
 *   GNU General Public License for more details.                            *
 *                                                                           *
 *   You should have received a copy of the GNU General Public License       *
 *   along with niwbillmanager. If not, see                                  *
 *   <http://www.gnu.org/licenses/>.                                         *
 *****************************************************************************/

#ifndef BACKENDINTERFACE_H
#define BACKENDINTERFACE_H

#include <QList>
#include <QSet>
#include <QtPlugin>

#include <billitem.h>
#include <transaction.h>

class BackendOpenMode
{
    public:
        enum BackendOpenModes {
            READ,
            WRITE,
        };
};

/**
 * An interface for backends.
 * This class is the bases of all backends. Every backend must implement this
 * interface.
 */
class BackendInterface
{
    public:
        virtual ~BackendInterface() {};

        /**
         * Open the collection.
         * @param openMode Specifies how the backend should be opened. READ
         * will check to ensure the collection is valid. WRITE will ensure
         * that the collection can be written to.
         * @param location The location of the collection.
         * Can be either a local file or a network address depending on the
         * backend implementation.
         * @param username Username within the associated collection. This is
         * for collections that have multiple users.
         * @param loginname The username to login for a remote connection.
         * @param password The password associated wtih remote connection
           login.
         * @return True if the collection was successfully opened.
         */
        virtual bool openCollection(BackendOpenMode::BackendOpenModes openMode,
            const QString &location,
            const QString &username="", const QString &loginname="",
            const QString &password="") = 0;
        /**
         * Checks to see if a collection is currently open.
         * @return True if the collection is currently open.
         */
        virtual bool isCollectionOpen() = 0;
        /**
         * Closes the collection.
         * This does not save or prompt to save. All changes elsewhere could
         * be lost.
         */
        virtual void closeCollection() = 0;

        /**
         * Checks to see if the backend can read incrementally.
         * A backend can optionally read items incrementally. If it can,
         * then items can either be read all at once or one at a time. If it
         * cannot, then retrieving items can only be done all at once.
         * libniwbillmanager prefers to read incrementally and will do so
         * possible.
         * @return True if the backend can read incrementally.
         * @see resetReadNextBillItem
         * @see hasMoreBillItems
         * @see readNextBillItem
         */
        virtual bool canReadIncremental() = 0;
        /**
         * Gets a list of all the bill items saved in the collection.
         * Can only be called after openCollection otherwise will fail.
         * @param &billItems A reference to a list to store the billitems in.
         * @return False on error.
         * @see openCollection
         * @see getLastErrorMessage
         */
        virtual bool readAllBillItems(QSet<BillItem> &billItems) = 0;
        /**
         * Sets readNextBillItem to the first bill item.
         * This can be optionally implemented. If it is not implemented then
         * canSaveIncremental will return false.
         * @return True if the successfully set to first bill item.
         * @see readNextBillItem
         * @see canReadIncremental
         */
        virtual bool startReadNextBillItem() = 0;
        /**
         * Checks to see if there are any bill items avaliable to retrieve
         * with readNextBillItem.
         * This can be optionally implemented. If it is not implemented then
         * canSaveIncremental will return false.
         * @return True if the collection has more bill items avaliable.
         * @see readNextBillItem
         * @see canReadIncremental
         */
        virtual bool hasMoreBillItems() = 0;
        /**
         * Retrieves the next bill item from the collection.
         * This will only work if the collection is open. Use hasMoreBillItems
         * to see if bill items are avaliable. Must be initalized without
         * resetReadNextBillItem.
         *
         * This can be optionally implemented. If it is not implemented then
         * canSaveIncremental will return false.
         * @param &billitem A reference to store the next bill item from the
         * collection.
         * @return True if successful.
         * @see openCollection
         * @see hasMoreBillItems
         * @see resetReadNextBillItem
         * @see canReadIncremental
         */
        virtual bool readNextBillItem(BillItem &billItem) = 0;

        /**
         * Save the bill items.
         * This does not update the collectioin it overwrites it.
         * @return True if all items were saved successfully
         */
        virtual bool saveAllBillItems(QSet<BillItem> billItems) = 0;
        /**
         * Checks to see if a backend can save a list of transactions.
         * A backend can optionally save items transactionally. If it can,
         * than items can be saved via transactions.
         *
         * libniwbillmanager prefers to save transactionally
         * @return True if the backend can save transactionally.
         * @see saveChange
         */
        virtual bool canSaveTransactional() = 0;
        /**
         * Checks to see if the backend can save all bills incrementally.
         * A backend can optionally save items incrementally. If it can,
         * then all items can be saved one after another.
         *
         * libniwbillmanager prefers to save incrementally if it cannot
         * save transactionally and will do so when possible.
         * @return True if the backend can save incrementally.
         * @see saveBillItem
         */
        virtual bool canSaveAllIncremental() = 0;
        /**
        * Saves a single change to disk.
        * This can be optionally implemented. If it is not implemented then
        * canSaveIncremental will return false.
        * @param transaction a transaction to be saved to disk.
        * @return True if the change was saved successfully.
        * @see canSaveIncremental
        */
        virtual bool saveChange(Transaction transaction) = 0;
        /**
         * Saves a bill item.
         * The bill item is appended.
         * @param billItem The bill item to save.
         * @return True if the bill was successfully saved.
         * @see canSaveAllIncremental
         */
        virtual bool saveBillItem(const BillItem &billItem) = 0;

        /**
         * Gets the last error message.
         * @return The error message
         */
        virtual QString getLastErrorMessage() = 0;

        /**
         * Check if the backend uses a remote connection to read and write to.
         * @return True if the backend utalizes a remote connection.
         */
        virtual bool isRemote() = 0;
        /**
         * Gets the name of the backend.
         * @return The name of the backend
         */
        virtual QString getName() = 0;
        /**
         * Gets the description of the backend.
         * @return The description of the backend
         */
        virtual QString getDescription() = 0;
        /**
         * Gets the version of the backend.
         * @return The description of the backend
         */
        virtual QString getVersion() = 0;

        /**
         * Gets the default file extension for local backends.
         * @return The file extension without the leading period.
         * This should return an empty string when called from a remote
         * backend.
         */
        virtual QString getDefaultFileExtenstion() = 0;
};

Q_DECLARE_INTERFACE(BackendInterface,
    "com.nachtimwald.projects.niwbillmanager.BackendInterface/1.2")

#endif /* BACKENDINTERFACE_H */
